package com.mvc.finance.web;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.extremecomponents.table.limit.Limit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.mvc.PdfUtils;
import com.mvc.ProjectUtils;
import com.mvc.base.model.Company;
import com.mvc.base.model.UserNotice;
import com.mvc.base.service.CustomerManager;
import com.mvc.business.model.OrderAssociated;
import com.mvc.business.model.Packing;
import com.mvc.business.service.OrderAssociatedManager;
import com.mvc.business.service.OrderManager;
import com.mvc.business.service.PackingManager;
import com.mvc.config.ApplicationConfig;
import com.mvc.finance.model.BankStatementCharge;
import com.mvc.finance.model.CommercialInvoice;
import com.mvc.finance.model.CommercialInvoiceCharge;
import com.mvc.finance.model.ExpenseApply;
import com.mvc.finance.service.CommercialInvoiceManager;
import com.mvc.framework.dao.PropertyFilter;
import com.mvc.framework.model.BaseEntity;
import com.mvc.framework.service.DictionaryFacade;
import com.mvc.framework.service.PageManager;
import com.mvc.framework.util.DomainUtils;
import com.mvc.framework.util.FileUpDownUtils;
import com.mvc.framework.util.FrameworkContextUtils;
import com.mvc.framework.util.PageSearch;
import com.mvc.framework.util.PageUtils;
import com.mvc.framework.web.PageController;
import com.mvc.portal.service.CUserManager;
import com.mvc.portal.service.NotificationManager;
import com.mvc.security.model.User;

@Controller
@RequestMapping("commercialInvoice")
public class CommercialInvoiceController extends PageController<CommercialInvoice> {

	private static final Logger	     LOGGER	= Logger.getLogger(CommercialInvoiceController.class);

	@Autowired
	private CommercialInvoiceManager	commercialInvoiceManager;

	@Autowired
	private PackingManager	         packingManager;

	@Autowired
	private CUserManager	         userManager;

	@Autowired
	private NotificationManager	     notificationManager;

	@Autowired
	private DictionaryFacade	     dictionaryFacade;

	@Autowired
	private CustomerManager	         customerManager;

	@Autowired
	private OrderAssociatedManager	 orderAssociatedManager;

	@Autowired
	private OrderManager	         orderManager;

	protected String handlePage(HttpServletRequest request, PageSearch page) {
		pageSettings(request);
		commercialInvoiceManager.find(page, null);
		return getFileBasePath() + "listCommercialInvoice";
	}

	protected void pageSettings(HttpServletRequest request) {
		request.setAttribute("action", "page");
		request.setAttribute("customers", customerManager.getAll());
	}

	protected String handleEdit(HttpServletRequest request, HttpServletResponse response, Integer id) throws Exception {
		if (null == id) {
			Packing entity = new Packing();
			// Invalid object id
			entity.setObjectId(-commercialInvoiceManager.createSystemId());
			request.setAttribute("entity", entity);
		} else {
			CommercialInvoice entity = getEntityManager().get(id);
			request.setAttribute("entity", entity);
			request.setAttribute("orderNo", orderAssociatedManager.getCommercialInvoiceOrderStr(entity.getObjectId()));
		}
		request.setAttribute("units", dictionaryFacade.getDictionariesByDictionaryId(1008));
		return getFileBasePath() + "editCommercialInvoice";
	}

	protected String handleSave(HttpServletRequest request, ModelMap modelMap, CommercialInvoice order) throws Exception {
		if (order.getId() == null) {
			order.setInvoiceDate(new Date());
			order.setStatus(ExpenseApply.STATUS_COMMIT);
		}
		getEntityManager().save(order);
		if (order.getStatus() == ExpenseApply.STATUS_COMMIT && order.getUserId() == FrameworkContextUtils.getCurrentUserId()) {
			List<User> users = userManager.getNoticeUsers(UserNotice.TYPE_COMMERCIAL_APPROVAL);
			if (users.size() > 0) {
				String subject = "商业发票提交通知(" + order.getNo() + ")";
				String content = "，您好：<br/>" + ProjectUtils.getParagraphIndent() + "编号为" + order.getNo() + "的商业发票已提交，请您登录<a href='"
				        + DomainUtils.getDynamicDomain() + "'>" + ApplicationConfig.getSystemName() + "</a>审批。<br/>"
				        + ProjectUtils.getCommonNoReplyMessage();
				for (User user : users) {
					try {
						notificationManager.sendMail(subject, user.getUserName() + content, new File[] {}, new String[] {},
						        ProjectUtils.getMailTo(user.getEmail()), new String[] {}, false);
					} catch (Exception e) {
						LOGGER.error("sendExpenseApprovalMessages", e);
					}
				}
			}
		}
		return "redirect:edit/" + ((BaseEntity) order).getId() + getMessage("common.base.success", request) + "&action="
		        + request.getParameter("action");
	}

	@RequestMapping("print/{orderId}")
	public String print(HttpServletRequest request, @PathVariable Integer orderId) {
		Map<String, Object> model = prepareOrderData(orderId, request);
		String orderContent = notificationManager.getTemplateString("commercialInvoice.html", model);
		request.setAttribute("orderContent", orderContent);
		return getFileBasePath() + "printCommercialInvoice";
	}

	@RequestMapping("notify/{orderId}")
	public String notify(@PathVariable Integer orderId, String purchasers, Boolean customer, ModelMap modelMap, HttpServletRequest request) {
		boolean result = false;
		try {
			String userEmails = purchasers;
			userEmails += ProjectUtils.EMAIL_SPLIT + request.getParameter("others");
			if (StringUtils.isNotBlank(userEmails) || customer) {
				Map<String, Object> model = prepareOrderData(orderId, request);
				String orderContent = notificationManager.getTemplateString("commercialInvoice.html", model);
				CommercialInvoice order = (CommercialInvoice) model.get("entity");
				if (customer) {
					userEmails += ProjectUtils.EMAIL_SPLIT + order.getCustomer().getEmail();
				}
				String[] to = ProjectUtils.getMailTo(userEmails);
				if (to != null && to.length > 0) {
					Company company = order.getCompany();
					String header = ProjectUtils.getPdfHeader(company);
					String footer = ProjectUtils.getPdfFooter(company);
					File file = PdfUtils.htmlToPdf(orderContent, header, footer);
					String subject = "Invoice(" + company.getName() + ":" + order.getNo() + ")";
					notificationManager.sendMail(subject, ProjectUtils.getENNoReplyMessage(), new File[] { file },
					        new String[] { order.getNo() + ".pdf" }, to, new String[] {}, true);
					result = true;
				}

			}
		} catch (Exception e) {
			LOGGER.error("notify", e);
		}
		modelMap.addAttribute("result", result);
		return "jsonView";
	}

	@RequestMapping("download/{orderId}")
	public String download(@PathVariable Integer orderId, HttpServletRequest request, HttpServletResponse response) {
		try {
			Map<String, Object> model = prepareOrderData(orderId, request);
			String orderContent = notificationManager.getTemplateString("commercialInvoice.html", model);
			CommercialInvoice order = (CommercialInvoice) model.get("entity");
			Company company = order.getCompany();
			String header = ProjectUtils.getPdfHeader(company);
			String footer = ProjectUtils.getPdfFooter(company);
			File file = PdfUtils.htmlToPdf(orderContent, header, footer);
			FileUpDownUtils.setDownloadResponseHeaders(response, order.getNo() + ".pdf");
			FileUpDownUtils.downloadFile(file, response);
		} catch (Exception e) {
			LOGGER.error("download", e);
		}
		return null;
	}

	protected Map<String, Object> prepareOrderData(Integer orderId, HttpServletRequest request) {
		CommercialInvoice order = commercialInvoiceManager.getObject(orderId);
		Map<String, Object> model = new HashMap<String, Object>();
		model.put("entity", order);
		model.put("orderItems", order.getCommercialInvoiceItems());
		model.put("chargeItems", order.getCommercialInvoiceCharges());
		model.put("currency", dictionaryFacade.getDictionaryByDictionaryIdAndValue(1006, order.getCurrency()).getName());
		model.put("staticDomain", ProjectUtils.getFullCssThemePath());
		model.put("groupName", ApplicationConfig.getGroupName());
		model.put("fontSize", ApplicationConfig.getFontSize());
		String orderNo = orderAssociatedManager.getCommercialInvoiceOrderStr(orderId);
		String clientPoNo = orderManager.getAssociatesOrderClientPoNo(orderId, OrderAssociated.TYPE_COMMERCIAL_INVOICE);
		List<Packing> packings = packingManager.getPackingsByCommercialInvoiceId(orderId);
		String packingNo = getPackingNo(packings);
		String sealNo = getSealNo(packings);
		String containerNo = getContainerNo(packings);
		List<CommercialInvoiceCharge> charges1 = new ArrayList<CommercialInvoiceCharge>();
		List<CommercialInvoiceCharge> charges2 = new ArrayList<CommercialInvoiceCharge>();
		for (CommercialInvoiceCharge charge : order.getCommercialInvoiceCharges()) {
			if (charge.getType() == BankStatementCharge.TYPE_FEE) {
				charges1.add(charge);
			} else if (charge.getType() == BankStatementCharge.TYPE_DEBIT) {
				charges2.add(charge);
			}
		}
		model.put("chargeItems1", charges1);
		model.put("chargeItems2", charges2);
		model.put("clientPoNo", clientPoNo);
		model.put("packingNo", packingNo);
		model.put("orderNo", orderNo);
		model.put("sealNo", sealNo);
		request.setAttribute("orderNo", orderNo);
		model.put("containerNo", containerNo);
		request.setAttribute("clientPoNo", clientPoNo);
		request.setAttribute("packingNo", packingNo);
		request.setAttribute("sealNo", sealNo);
		request.setAttribute("containerNo", containerNo);
		request.setAttribute("fontSize", ApplicationConfig.getFontSize());
		request.setAttribute("entity", order);
		request.setAttribute("currency", dictionaryFacade.getDictionaryByDictionaryIdAndValue(1006, order.getCurrency()).getName());
		request.setAttribute("staticDomain", ProjectUtils.getFullCssThemePath());
		request.setAttribute("groupName", ApplicationConfig.getGroupName());
		return model;
	}

	public String getPackingNo(List<Packing> packings) {
		if (packings.size() > 0) {
			StringBuilder result = new StringBuilder();
			for (Packing associated : packings) {
				result.append(ProjectUtils.getPackingNo(associated.getObjectId())).append(", ");
			}
			return result.substring(0, result.length() - 2);
		}
		return "";
	}

	public String getSealNo(List<Packing> packings) {
		if (packings.size() > 0) {
			StringBuilder result = new StringBuilder();
			for (Packing associated : packings) {
				if (StringUtils.isNotBlank(associated.getSealNo())) {
					result.append(associated.getSealNo()).append(", ");
				}
			}
			if (result.length() > 0) {
				return result.substring(0, result.length() - 2);
			}
		}
		return "";
	}

	public String getContainerNo(List<Packing> packings) {
		if (packings.size() > 0) {
			StringBuilder result = new StringBuilder();
			for (Packing associated : packings) {
				if (StringUtils.isNotBlank(associated.getContainerNo())) {
					result.append(associated.getContainerNo()).append(", ");
				}
			}
			if (result.length() > 0) {
				return result.substring(0, result.length() - 2);
			}
		}
		return "";
	}

	@RequestMapping("my")
	public String my(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Limit limit = PageUtils.getLimit(request);
		PageSearch page = preparePage(request, limit);
		pageSettings(request);
		// commercialInvoiceManager.find(page,
		// FrameworkContextUtils.getCurrentUserId());
		page.getFilters().add(new PropertyFilter("EQI_userId", FrameworkContextUtils.getCurrentUserId() + ""));
		handlePage(request, page);
		afterPage(request, page, IS_NOT_BACK);
		request.setAttribute("action", "my");
		return getFileBasePath() + "listCommercialInvoice";
	}

	@RequestMapping("selectToPacking")
	public String selectToPacking(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Limit limit = PageUtils.getLimit(request);
		PageSearch page = preparePage(request, limit);
		if (StringUtils.isNotBlank(request.getParameter("customerId"))) {
			page.getFilters().add(new PropertyFilter("EQI_customerId", request.getParameter("customerId")));
		}
		handlePage(request, page);
		afterPage(request, page, IS_NOT_BACK);
		request.setAttribute("action", "selectToPacking");
		return getFileBasePath() + "selectCommercialInvoice";
	}

	@RequestMapping("audit")
	public String audit(HttpServletRequest request, HttpServletResponse response) throws Exception {
		Limit limit = PageUtils.getLimit(request);
		PageSearch page = preparePage(request, limit);
		page.getFilters().add(new PropertyFilter("EQI_status", ExpenseApply.STATUS_COMMIT + ""));
		handlePage(request, page);
		afterPage(request, page, IS_NOT_BACK);
		request.setAttribute("action", "audit");
		return getFileBasePath() + "listCommercialInvoice";
	}

	@RequestMapping("audit/{orderId}")
	public String audit(HttpServletRequest request, ModelMap modelMap, @PathVariable Integer orderId) {
		boolean result = false;
		if (orderId != null) {
			try {
				CommercialInvoice order = commercialInvoiceManager.getByObjectId(orderId);
				if (order.getStatus() == ExpenseApply.STATUS_COMMIT) {
					order.setStatus(ExpenseApply.STATUS_APPROVAED);
					order.setApprovalUserId(FrameworkContextUtils.getCurrentUserId());
					order.setApprovalDate(new Date());
					commercialInvoiceManager.save(order);
					User applier = userManager.getByObjectId(order.getUserId());
					String subject = "商业发票审批完成通知(" + order.getNo() + ")";
					String content = "，您好：<br/>" + ProjectUtils.getParagraphIndent() + "编号为" + order.getNo() + "的商业发票已审批，请您登录<a href='"
					        + DomainUtils.getDynamicDomain() + "'>" + ApplicationConfig.getSystemName() + "</a>查看详情。<br/>"
					        + ProjectUtils.getCommonNoReplyMessage();
					try {
						notificationManager.sendMail(subject, applier.getUserName() + content, new File[] {}, new String[] {},
						        ProjectUtils.getMailTo(applier.getEmail()), new String[] {}, false);
					} catch (Exception e) {
						LOGGER.error("sendCommercialInvoiceApprovedMessages", e);
					}
					result = true;
				}
			} catch (Exception e) {
				LOGGER.error("audit:" + orderId, e);
			}
		}
		modelMap.put("result", result);
		return "jsonView";
	}

	@RequestMapping("backward/{orderId}")
	public String backward(HttpServletRequest request, ModelMap modelMap, @PathVariable Integer orderId) {
		boolean result = false;
		if (orderId != null) {
			try {
				CommercialInvoice order = commercialInvoiceManager.getByObjectId(orderId);
				if (order.getStatus() != ExpenseApply.STATUS_PAYED) {
					String reason = request.getParameter("reason");
					order.setStatus(ExpenseApply.STATUS_BACKWARD);
					order.setApprovalUserId(null);
					order.setBackwardReason(reason);
					commercialInvoiceManager.save(order);
					User applier = userManager.getByObjectId(order.getUserId());
					String subject = "商业发票审批退回通知(" + order.getNo() + ")";
					String content = "，您好：<br/>" + ProjectUtils.getParagraphIndent() + "编号为" + order.getNo() + "的商业发票已退回，原因为：" + reason
					        + "。请您登录<a href='" + DomainUtils.getDynamicDomain() + "'>" + ApplicationConfig.getSystemName()
					        + "</a>查看详情。<br/>" + ProjectUtils.getCommonNoReplyMessage();
					try {
						notificationManager.sendMail(subject, applier.getUserName() + content, new File[] {}, new String[] {},
						        ProjectUtils.getMailTo(applier.getEmail()), new String[] {}, false);
					} catch (Exception e) {
						LOGGER.error("sendCommercialInvoiceBackwardMessages", e);
					}
					result = true;
				} else {
					modelMap.addAttribute("message", "已经付款了，不能再修改。");
				}
			} catch (Exception e) {
				LOGGER.error("backward" + orderId, e);
			}
		}
		modelMap.put("result", result);
		return "jsonView";
	}

	@RequestMapping("pay/{orderId}")
	public String pay(HttpServletRequest request, @PathVariable Integer orderId, ModelMap modelMap) throws Exception {
		boolean result = false;
		if (orderId != null) {
			try {
				CommercialInvoice order = commercialInvoiceManager.getByObjectId(orderId);
				if (order != null && order.getStatus() == ExpenseApply.STATUS_APPROVAED) {
					order.setStatus(ExpenseApply.STATUS_PAYED);
					order.setPayDate(new Date());
					commercialInvoiceManager.save(order);
				}
				result = true;
			} catch (Exception e) {
				LOGGER.error("pay:" + orderId, e);
			}
		}
		modelMap.put("result", result);
		return "jsonView";
	}

	@Override
	public PageManager<CommercialInvoice> getEntityManager() {
		return commercialInvoiceManager;
	}

	@Override
	public String getFileBasePath() {
		return "finance/";
	}

}
